package com.ygqh.baby.service.trustone;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.http.HttpHeaders;
import com.foxinmy.weixin4j.util.StringUtil;
import com.ygqh.baby.ao.PayType;
import com.ygqh.baby.cache.RedisCacheStorager;
import com.ygqh.baby.exception.CacheException;
import com.ygqh.baby.exception.YgHttpException;
import com.ygqh.baby.http.YgRequestExecutor;
import com.ygqh.baby.http.YgResponse;
import com.ygqh.baby.model.OrderSkuTaxRates;
import com.ygqh.baby.model.OrderTaxes;
import com.ygqh.baby.po.YgOrder;
import com.ygqh.baby.po.YgOrderDetail;
import com.ygqh.baby.po.YgReturnOrder;
import com.ygqh.baby.po.YgReturnOrderDetail;
import com.ygqh.baby.service.YgOrderDetailService;
import com.ygqh.baby.service.YgOrderService;
import com.ygqh.baby.service.YgSkuCombinationService;
import com.ygqh.baby.service.trustone.model.*;
import com.ygqh.baby.token.Token;
import com.ygqh.baby.token.TokenManager;
import com.ygqh.baby.utils.ExceptionUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class TrustoneApi {
    private Logger logger = LoggerFactory.getLogger(getClass());

    private TruStoneTokenCreator tokenCreator = new TruStoneTokenCreator();
    private YgRequestExecutor requestExecutor = new YgRequestExecutor();

    @Autowired
    private RedisCacheStorager<Token> cacheStorager;
    @Autowired
    private YgOrderService ygOrderService;
    @Autowired
    private YgOrderDetailService ygOrderDetailService;
    @Autowired
    private YgSkuCombinationService ygSkuCombinationService;

    private TokenManager tokenManager;

    @Value("${trustoner.supplier.id}")
    private Long trustonerSupplierId;

    @PostConstruct
    public void init() {
        tokenManager = new TokenManager(tokenCreator, cacheStorager);
    }

    public String getAccessToken() throws CacheException {

        return tokenManager.getAccessToken();

    }

    public ApiResult pushOrder(TruStoneAddOrderReq req) throws YgHttpException {
        OrderRequestParam orderRequestParam;

        if (!req.isChange()) {
            YgOrder order = req.getOrder();
            List<YgOrderDetail> orderDetailList = order.getOrderDetail().stream().filter(od -> trustonerSupplierId.equals(od.getSupplierId())).collect
                    (Collectors.toList());
            orderDetailList = ygSkuCombinationService.reassemblyOrderDetails(orderDetailList);
            order.setOrderDetail(orderDetailList);

            orderRequestParam = this.buildOrderRequestParam(order, req.getIdentityNo(), req.getOutTradeNo(), req.getTransactionId(), req.getPayType());
        } else {
            // orderRequestParam = buildChangeRequestParam(req.getChangeOrder(),
            // IdNumber);
            return new ApiResult(400, true, "保税仓订单不支持退换货");
        }
        String param = JSON.toJSONString(orderRequestParam);

        return this.doPost(TrustoneConfig.getAddorderapi(), param);

    }

    private OrderRequestParam buildOrderRequestParam(YgOrder order, String idNumber, String outTradeNo, String transactionId, PayType payType) {
        List<OrderSkuTaxRates> orderSkuTaxRates = ygOrderDetailService.getOrderSkuTaxRates(order.getOrderId());
        List<SellOrderListVos> sellOrderListVos = new ArrayList<>();
        List<OrderSkuTaxRates> newSkuTaxRates = new ArrayList<>();
        for (int i = 0; i < order.getOrderDetail().size(); i++) {
            YgOrderDetail od = order.getOrderDetail().get(i);
            for (OrderSkuTaxRates rate : orderSkuTaxRates) {
                if (od.getId().equals(rate.getOdId())) {
                    OrderSkuTaxRates cloneRate = rate.clone();
                    SellOrderListVos detail = new SellOrderListVos();
                    detail.setGoodsHscode(od.getOutSkuCode());
                    detail.setGoodsName(od.getProductName());
                    cloneRate.setSalePrice(od.getSalePrice());
                    cloneRate.setQuantity(od.getQuantity());
                    BigDecimal realSale = rate.getRealPrice();
                    detail.setGoodsPrice(realSale);
                    detail.setGoodsQuantity(od.getQuantity().intValue());
                    detail.setGoodsSequence(i + 1);
                    detail.setGoodsSku(od.getOutSkuCode());
                    sellOrderListVos.add(detail);
                    newSkuTaxRates.add(cloneRate);
                }
            }
        }
        OrderRequestParamBuilder builder = new OrderRequestParamBuilder(payType);

        builder.buildOrderCode(order.getOrderId().toString(), 1, outTradeNo, "", transactionId);
        builder.buildBuyer(order.getReceiver(), order.getTelPhone(), order.getTelPhone(), "1", idNumber);
        builder.buildReceiverInfo(order.getReceiver(), order.getTelPhone(), "中国", order.getProvinceName(), order.getCityName(), order.getAreaName(), order
                .getAddress());
        builder.buildPayerInfo(order.getReceiver(), "1", idNumber);
        builder.buildPushStatus(1, 1, 0);
        builder.buildObtainStatus(1, 1);

        OrderTaxes orderTaxes = ygOrderDetailService.getOrderTaxes(order.getOrderId(), newSkuTaxRates);
        builder.buildTax(orderTaxes);
        BigDecimal realProductPrice = order.getOrderDetail().stream().map(od -> od.getSalePrice().multiply(new BigDecimal(od.getQuantity()))).reduce
                (BigDecimal.ZERO, BigDecimal::add);
        BigDecimal noCashDeduction = realProductPrice.subtract(order.getExpressPrice()).subtract(order.getTotalPrice());

        // orderTotalFee = orderTotalValue + orderTotalTax + shippingFee -noCashDeduction
        //orderTotalValue 订单总货值
        BigDecimal orderTotalValue = realProductPrice.subtract(orderTaxes.getTariff()).subtract(orderTaxes.getSaleTax());
        //总费用=订单总货值+税费+运费-其他费用（优惠卷）
        builder.buildPrice(order.getTotalPrice(), orderTotalValue, order.getExpressPrice(), noCashDeduction);
        OrderRequestParam orderRequestParam = builder.build();
        orderRequestParam.setSellOrderListVos(sellOrderListVos);

        return orderRequestParam;

    }

    private OrderRequestParam buildChangeRequestParam(YgReturnOrder order, String idNumber) throws YgHttpException {

        OrderRequestParamBuilder builder = new OrderRequestParamBuilder(order.getPayType());

        builder.buildOrderCode(order.getReturnCode(), 1, order.getReturnCode(), "", order.getReturnCode());
        builder.buildBuyer(order.getReceiver(), order.getTelPhone(), order.getTelPhone(), "1", idNumber);
        builder.buildReceiverInfo(order.getReceiver(), order.getTelPhone(), "中国", order.getProvinceName(), order.getCityName(), order.getAreaName(), order
                .getAddress());
        builder.buildPayerInfo(order.getReceiver(), "1", idNumber);
        builder.buildPushStatus(1, 1, 0);
        builder.buildObtainStatus(1, 1);

        builder.buildTax(BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO);

        // orderTotalFee = orderTotalValue + orderTotalTax + shippingFee -
        // noCashDeduction
        builder.buildPrice(BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO);
        OrderRequestParam orderRequestParam = builder.build();

        List<SellOrderListVos> sellOrderListVos = new ArrayList<>();
        for (YgReturnOrderDetail od : order.getReturnOrderDetails()) {
            if (od.getSupplierId() != 1000L) {
                continue;
            }
            SellOrderListVos detail = new SellOrderListVos();
            detail.setGoodsHscode(od.getSkuCode());
            detail.setGoodsName(od.getProductName());
            detail.setGoodsPrice(od.getSalePrice());
            detail.setGoodsQuantity(od.getQuantity().intValue());
            detail.setGoodsSequence(od.getSkuId().intValue());
            detail.setGoodsSku(od.getSkuCode());
            //            detail.setGoodsSku("4013718021065");
            sellOrderListVos.add(detail);
        }
        orderRequestParam.setSellOrderListVos(sellOrderListVos);

        return orderRequestParam;

    }

    /**
     * @param orderUuid    销售订单入库时的 uuid String 32 true
     * @param orderno      订单号码 String 30 false
     * @param cbecode      电商企业代码 String 15 false
     * @param cancelReason 订单取消原因 String 200 false
     * @return ApiResult    返回类型
     * @throws YgHttpException 入参
     * @throws
     * @Title: cancelorder
     * @author （guohao）
     * @date 2018年6月28日 下午6:07:47
     * @version V1.0
     */
    private ApiResult cancelorder(String orderUuid, String orderno, String cbecode, String cancelReason) throws YgHttpException {

        Map<String, String> param = new HashMap<>();
        param.put("orderUuid", orderUuid);
        if (StringUtil.isNotBlank(orderno)) {
            param.put("orderno", orderno);
        }
        if (StringUtils.isNotBlank(cancelReason)) {
            param.put("cancelReason", cancelReason);
        }

        // String url =
        // "http://123.207.153.164:9000/api/ordersys/sellCancelrecords/cancelorder";

        return this.doPost(TrustoneConfig.getCancelorderapi(), JSON.toJSONString(param));

    }

    public ApiResult cancelorder(String orderId, String cancelReason) throws YgHttpException {

        return this.cancelorder(orderId, null, TrustoneConfig.getEbusinessqstcode(), cancelReason);

    }

    private ApiResult doPost(String url, String body) throws YgHttpException {
        HttpHeaders headers = new HttpHeaders();
        String accessToken = doGetAccessToken();
        headers.set("accessToken", accessToken);
        headers.set("Content-Type", "application/json");
        logger.info("Trustone push order param:【" + body + "】");
        YgResponse response = requestExecutor.post(url, headers, body);
        logger.info("Trustone push order result:【" + response.getAsString() + "】");

        this.handleResponse(response);
        return response.getAsObject(new TypeReference<ApiResult>() {
        });
    }

    private String doGetAccessToken() throws YgHttpException {
        try {
            return tokenManager.getAccessToken();
        } catch (CacheException e) {
            logger.error("获取全速通 AccessToken 失败，{}", ExceptionUtil.getExceptionMsg(e));
            e.printStackTrace();
            throw new YgHttpException(e);
        }

    }

    protected void handleResponse(YgResponse response) throws YgHttpException {
        TypeReference<ApiResult> typeReference = new TypeReference<ApiResult>() {
        };
        String asString = response.getAsString();
        System.out.println(asString);
        ApiResult result = response.getAsObject(typeReference);
        if (result.getStatus() != 200) {
            throw new YgHttpException(result.getStatus() + "", result.getMessage());
        }
    }

    public Boolean trustoneAddOrder(YgDeclareCustomsResult declareCustoms) throws YgHttpException {
        YgOrder order = ygOrderService.findOrderDetailByOrderId(declareCustoms.getOrderId());
        TruStoneAddOrderReq req = new TruStoneAddOrderReq();
        req.setOrder(order);
        req.setOutTradeNo(declareCustoms.getOutTradeNo());
        req.setTransactionId(declareCustoms.getTransactionId());
        return this.trustoneAddOrder(req);
    }

    /**
     * 暂时 只支持订单（不支持换货单）调用时注意
     *
     * @param req
     * @return Boolean    返回类型
     * @throws YgHttpException 入参
     * @Title: trustoneAddOrder
     * @author （guohao）
     * @date 2018年11月22日 上午10:05:33
     * @version V1.0
     */
    public Boolean trustoneAddOrder(TruStoneAddOrderReq req) throws YgHttpException {
        ApiResult result = this.pushOrder(req);
        if (result.isRel() && result.getStatus() == 200) {
            YgOrder ygOrder = new YgOrder();
            ygOrder.setOrderId(req.getOrder().getOrderId());
            ygOrder.setWdtOrderCode("Tru" + ygOrder.getOrderId());
            ygOrderService.updateByOrderId(ygOrder);
            return true;

        }
        return false;
    }
}
